%token IDENTIFIER STRING_LITERAL CHAR_LITERAL CONST_NUM
%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP
%token CHAR INT FLOAT
%token IF ELSE WHILE DO FOR
%token READ WRITE ENDL
%token STRCMP SUBSTR FINDSUBSTR STRLEN

%start main_statement
%%

ext_variable
	: ext_variable '[' additive_expression ']'
	|
	;
	
variable_
	: IDENTIFIER ext_variable
	;

primary_expression
	: variable_
	| STRING_LITERAL
	| CHAR_LITERAL
	| CONST_NUM
	;

postfix_expression
        : primary_expression
        | '(' logical_or_expression ')'
        | variable_ INC_OP
        | variable_ DEC_OP
        ;


unary_expression
        : postfix_expression
        | '-' unary_expression
        ;


multiplicative_expression
        : unary_expression
        | multiplicative_expression '*' unary_expression
        | multiplicative_expression '/' unary_expression
        ;

additive_expression
	: multiplicative_expression
	| additive_expression '+' multiplicative_expression
	| additive_expression '-' multiplicative_expression
	;

relational_expression
	: additive_expression
	| relational_expression '<' additive_expression
	| relational_expression '>' additive_expression
	| relational_expression LE_OP additive_expression
	| relational_expression GE_OP additive_expression
	;

equality_expression
	: relational_expression
	| equality_expression EQ_OP relational_expression
	| equality_expression NE_OP relational_expression
	;

logical_and_expression
	: equality_expression
	| logical_and_expression AND_OP equality_expression
	;

logical_or_expression
	: logical_and_expression
	| logical_or_expression OR_OP logical_and_expression
	;

assignment_expression
	: logical_or_expression
	| primary_expression '=' logical_or_expression
	;

declaration_
	: declaration_specifiers ';'
	| declaration_specifiers init_declarator_list ';'
	;

declaration_specifiers
	: type_specifier
	| type_specifier declaration_specifiers
	;

init_declarator_list
	: init_declarator
	;

init_declarator
	: direct_declarator
	;

type_specifier
	: CHAR
	| INT
	| FLOAT
	;

direct_declarator
	: IDENTIFIER
	| direct_declarator '[' additive_expression ']'
	| direct_declarator '[' ']'
	;

initializer_
	: assignment_expression
	| '{' initializer_list '}'
	| '{' initializer_list ',' '}'
	;

initializer_list
	: initializer_
	| initializer_list ',' initializer_
	;

statement_
	: compound_statement
	| expression_statement
	| selection_statement
	| iteration_statement
	| io_statement
	| str_statement
	;
	
main_statement
	: '{' '}'
	| '{' statement_list '}'
	| '{' declaration_list '}'
	| '{' declaration_list statement_list '}'
	;

compound_statement
	: '{' '}'
	| '{' statement_list '}'
	;

declaration_list
	: declaration_
	| declaration_list declaration_
	;

statement_list
	: statement_
	| statement_list statement_
	;

expression_statement
	: ';'
	| assignment_expression ';'
	;

selection_statement
	: IF '(' logical_or_expression ')' statement_ selection_statement_2
	;

selection_statement_2
	: ';'
	| ELSE statement_ ';'
	;

iteration_statement
	: WHILE '(' logical_or_expression ')' statement_
	| DO statement_ WHILE '(' logical_or_expression ')' ';'
	| FOR '(' variable_ ';' logical_or_expression ';' additive_expression ')' statement_
	;

io_statement
	: READ '(' primary_expression ')'
	| WRITE '(' primary_expression ')'
	| ENDL  '(' ')'
	;
	
str_statement
	: STRCMP '(' variable_ ',' variable_ ',' variable_  ')'
	| FINDSUBSTR  '(' variable_ ',' variable_ ',' variable_ ')'
	| STRLEN  '(' variable_ ',' variable_ ')'
	;

%%
#include <stdio.h>

extern char yytext[];
extern int column;

yyerror(s)
char *s;
{
	fflush(stdout);
	printf("\n%*s\n%*s\n", column, "^", column, s);
}
